package com.xb.loan.token.factory.utils;

import com.xb.loan.token.factory.monitor.ShootingMonitor;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.PersistenceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Timer;

/**
 * User: erin
 * Date: 15/4/27
 * Time: 上午9:54
 */
public class EhcacheUtil {

    private static final Logger logger = LoggerFactory.getLogger(EhcacheUtil.class);
    private static final String CACHE_PREFIX = "cache_";
     static final int DEFAULT_EHCACHE_EXPIRE = 10 * 60;

    private static CacheManager cacheManager = null;
    private static CacheConfiguration cacheConfiguration = null;

    private static int maxElements = 1000000;
    private static int cacheInstanceSize = 10;
    private static int cacheExpire = DEFAULT_EHCACHE_EXPIRE;

    private static Map<String, Cache> caches = new HashMap();

    public static void init() {
        if (cacheConfiguration == null) {
            cacheConfiguration = new CacheConfiguration();
            int maxElementsPerCache = (maxElements + cacheInstanceSize - 1) / cacheInstanceSize;  // 设置单个cache的缓存为ceil(平均数)
            cacheConfiguration.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE));
            cacheConfiguration.setEternal(false);   // 不永久存储
            cacheConfiguration.setTimeToLiveSeconds(cacheExpire);   // 默认过期时间
            cacheConfiguration.setMaxEntriesLocalHeap(maxElementsPerCache);     // 测试发现，此数值为单个cache的最大记录数
        }
        Configuration configuration = new Configuration();
        configuration.setDefaultCacheConfiguration(cacheConfiguration);

        cacheManager = new CacheManager(configuration);

        Timer timer = new Timer();
        timer.schedule(new ShootingMonitor(), 60 * 1000l, 60 * 1000l);

    }

    public void stop() {
        getCacheManagerInstance().shutdown();
    }

    public static String get(String key) {
        String cacheKey = getCacheKey(key);
        if (cacheKey.isEmpty()) {
            return null;
        }
        Cache cache = getCacheInstance(cacheKey);

        String value = null;
        if (cache != null) {
            Element element = cache.get(key);
            value = element == null ? null : (String) element.getObjectValue();
        }
        return value;
    }

    public static void remove(String key) {
        String cacheKey = getCacheKey(key);
        if (cacheKey.isEmpty()) {
            return;
        }
        Cache cache = getCacheInstance(cacheKey);

        boolean value = false;
        if (cache != null) {
            Element element = cache.get(key);
            value = element != null && cache.remove(key);
        }
    }

    public static void set(String key, String value) {
        String cacheKey = getCacheKey(key);
        if (cacheKey.isEmpty()) {
            return;
        }
        Cache cache = getCacheInstance(cacheKey);

        if (cache != null) {
            cache.put(new Element(key, value));
        }
    }

    /*
     * 获取cache实例
     */
    private static Cache getCacheInstance(String cacheKey) {
        if (cacheKey.isEmpty()) {
            return null;
        }
        Cache cache = caches.get(cacheKey);
        if (cache == null) {
            cache = getCacheManagerInstance().getCache(cacheKey);
            if (cache == null) {
                synchronized (cacheManager) {
                    cache = getCacheManagerInstance().getCache(cacheKey);
                    if (cache == null) {
                        getCacheManagerInstance().addCache(cacheKey);
                        cache = getCacheManagerInstance().getCache(cacheKey);
                    }
                }
            }
            caches.put(cacheKey, cache);
        }
        return cache;
    }

    /*
     * 获取CacheManager实例
     */
    private static CacheManager getCacheManagerInstance() {
        if (cacheManager == null) {
            synchronized (CacheManager.class) {
                if (cacheManager == null) {
                    init();
                }
            }
        }
        return cacheManager;
    }

    /*
     * 根据key进行MD5，之后再转换为十进制取模
     */
    private static String getCacheKey(String key) {
        try {
            return CACHE_PREFIX + Integer.parseInt(Coder.encryptMD5(key).substring(28), 16) % getCacheInstanceSize();
        } catch (Exception e) {
            return null;
        }

    }


    public static int getCacheInstanceSize() {
        return cacheInstanceSize;
    }


    /**
     * 获取cache命中数
     *
     * @return
     */
    public static long getCacheHits() {
        long hits = 0l;
        try {
            String[] cacheNames = getCacheManagerInstance().getCacheNames();
            for (String cacheName : cacheNames) {
                Cache cache = getCacheManagerInstance().getCache(cacheName);
                hits += cache.getStatistics().cacheHitCount();
            }
        } catch (Exception e) {
            logger.error("ehcache getCacheHits error:", e);
        }

        return hits;
    }

    /**
     * 获取cache丢失数
     *
     * @return
     */
    public static long getCacheMisses() {
        long misses = 0l;
        try {
            String[] cacheNames = getCacheManagerInstance().getCacheNames();
            for (String cacheName : cacheNames) {
                Cache cache = getCacheManagerInstance().getCache(cacheName);
                misses += cache.getStatistics().cacheMissCount();
            }
        } catch (Exception e) {
            logger.error("ehcache getCacheMisses error:", e);
        }

        return misses;
    }

}
